import { Request, Response } from 'express';
import uploadFile, {
    generateVideoThumbnail,
    generateImageThumbnail,
    generateVideoHls,
} from '../utils/upload.file';
import path from 'path';
import fse from 'fs-extra';
import 'express-async-errors'
import { FILE_SIZE_LIMIT, FILE_UPLOAD_DIR, COVER_UPLOAD_DIR, HLS_UPLOAD_DIR } from '../constants/normal.constants';
import { DownloadInput, SendMessageInput } from '../schemas/message.schemas';
import processMessage from '../websocket/process'

class MessageController {
    async sendMessage(req: Request, res: Response) {
        const { userId } = req.auth
        const { contactId, isGroup, content, type, fileSize, fileName, fileType, fileUuid } = req.body as SendMessageInput;

        const { success, message } = await processMessage({
            senderId: userId,
            receiverId: isGroup ? undefined : contactId,
            groupId: isGroup ? contactId : undefined,
            content,
            type,
            fileSize,
            fileName,
            fileType,
            fileUuid
        })
        if (!success) {
            res.status(400).json({ message })
            return
        }
        res.send({ message })
    }
    async uploadFile(req: Request, res: Response) {
        uploadFile(req, res, async (err: any) => {
            if (err) {
                let message = "file upload fail";
                if (err.code === "LIMIT_FILE_SIZE") {
                    message = `file size over ${FILE_SIZE_LIMIT / 1024 / 1024}MB limit`;
                } else if (err.code === "INVALID_FILE_TYPE") {
                    message = err.message;
                } else if (err.code === "LIMIT_UNEXPECTED_FILE") {
                    message = "only one file";
                }
                res.status(400).json({ message });
                return
            }

            const file = req.file;
            if (!file) {
                res.status(400).json({ message: "no file upload" });
                return
            }

            const uuid = file.filename.split('.')[0]; // 去掉扩展名
            const type = file.mimetype;
            const ext = path.extname(file.originalname).toLowerCase();

            const filePath = path.resolve(FILE_UPLOAD_DIR, uuid + ext);
            const coverPath = path.resolve(COVER_UPLOAD_DIR, uuid + ".jpg");

            if (type.startsWith("image/")) {
                await generateImageThumbnail(filePath, coverPath);
            } else if (type.startsWith("video/")) {
                const hlsDir = path.resolve(HLS_UPLOAD_DIR, uuid, "index.m3u8");
                await generateVideoThumbnail(filePath, coverPath);
                await generateVideoHls(filePath, hlsDir);
            }
            res.send({ message: "file uploaded", uuid });
        });
    }

    async downloadFile(req: Request, res: Response) {
        const { uuid } = req.query as DownloadInput;
        if (!uuid) {
            res.status(400).json({ message: "uuid is required" });
            return;
        }

        const files = await fse.readdir(FILE_UPLOAD_DIR)
        const file = files.find((item) => item.startsWith(uuid))
        if (!file) {
            res.status(400).json({ message: "file not found" });
            return;
        }
        const ext = path.extname(file);
        const filePath = path.resolve(FILE_UPLOAD_DIR, file);
        res.sendFile(filePath, {
            headers: {
                headers: {
                    'Content-Disposition': `attachment; filename="${uuid}${ext}"`
                }
            }
        });
    }

    async downloadCover(req: Request, res: Response) {
        const { uuid } = req.query;
        if (!uuid) {
            res.status(400).json({ message: "uuid is required" });
            return;
        }
        const coverPath = path.resolve(COVER_UPLOAD_DIR, uuid + ".jpg");
        if (!fse.existsSync(coverPath)) {
            res.status(400).json({ message: "cover not found" });
            return;
        }
        res.sendFile(coverPath, {
            headers: {
                headers: {
                    'Content-Disposition': `attachment; filename="${uuid}.jpg"`
                }
            }
        });
    }
}

const messageController = new MessageController();
export default messageController;